<!--
  <script> 标签部分主要用于编写组件的逻辑代码，使用 Vue 3 的 <script setup> 语法糖。
  在这个部分，我们可以导入组件、定义响应式数据、编写方法等。
  这里导入了两个自定义组件 RightToolbar 和 Pagination，同时引入了接口请求函数 listProductUnit 和 addProductUnit，
  并定义了分页列表数据、总记录数、加载动效控制、搜索显示控制、新增与修改弹出层等响应式数据，以及相关操作方法。
-->
<script name="ProductUnit" setup>
// 从 Vue 中导入 getCurrentInstance 函数，用于获取当前组件实例，以便访问组件的属性和方法
// 导入 reactive 函数，用于创建响应式对象，适合管理复杂的对象数据
// 导入 ref 函数，用于创建响应式数据，适合管理基本类型的数据
// 导入 toRefs 函数，用于将响应式对象的属性转换为响应式引用，方便在模板中使用
import { getCurrentInstance, reactive, ref, toRefs } from 'vue';
// 导入右侧工具栏组件，用于在页面右侧提供额外的操作功能，如搜索框显示控制等
import RightToolbar from "@/components/RightToolbar/index.vue";
// 导入分页组件，用于对数据进行分页展示，方便用户浏览大量数据
import Pagination from "@/components/Pagination/index.vue";
// 导入从 API 模块中获取产品单位列表的接口函数，用于请求商品单位列表数据
// 导入获取单个产品单位详细信息的接口函数，用于根据 ID 获取商品单位的详细信息
// 导入添加产品单位的接口函数，用于向服务器新增商品单位
// 导入更新产品单位的接口函数，用于修改已有的商品单位信息
import {
    addProductUnit,
    deleteProductUnit,
    getProductUnit,
    listProductUnit,
    updateProductUnit
} from "@/api/base/productUnit.js";

// 获取当前组件实例，通过解构赋值得到 proxy，proxy 可用于访问组件实例的属性和方法，如调用组件内的方法、访问全局变量等
const { proxy } = getCurrentInstance();

// 定义分页列表数据模型，使用 ref 创建响应式数组，初始为空数组，用于存储从服务器获取的产品单位列表数据
const productUnitList = ref([]);
// 定义列表总记录数模型，使用 ref 创建响应式变量，初始值为 0，用于存储产品单位的总记录数，方便分页计算
const total = ref(0);
// 加载数据时显示的动效控制模型，使用 ref 创建响应式变量，初始值为 true 表示正在加载，用于控制加载动效的显示与隐藏
const loading = ref(true);
// 定义隐藏搜索控制模型，使用 ref 创建响应式变量，初始值为 true 表示显示搜索框，用于控制搜索框的显示与隐藏
const showSearch = ref(true);
// 新增与修改弹出层标题模型，使用 ref 创建响应式变量，用于存储弹出层的标题，根据操作类型动态显示不同标题
const title = ref("");
// 新增与修改弹出层控制模型，使用 ref 创建响应式变量，用于控制弹出层的显示与隐藏，方便用户进行新增或修改操作
const open = ref(false);
// 定义批量操作 id 列表模型，使用 ref 创建响应式数组，用于存储选中的产品单位的 id，方便进行批量删除等操作
const ids = ref([]);
// 定义单选控制模型，使用 ref 创建响应式变量，用于控制修改按钮的禁用状态，当只选中一条记录时可进行修改操作
const single = ref(true);
// 定义多选控制模型，用于控制删除按钮的禁用状态，当有选中记录时可进行删除操作
const multiple = ref(true);

// 使用 reactive 创建响应式对象，包含搜索相关的参数、表单数据和表单验证规则
const data = reactive({
    // 定义搜索模型，包含页码、每页数量和搜索关键词，用于筛选商品单位列表数据
    queryParams: {
        pageNum: 1, // 当前页码，初始值为 1，用于指定从第几页开始加载数据
        pageSize: 10, // 每页显示的记录数，初始值为 10，用于控制每页显示的商品单位数量
        name: null // 搜索关键词，初始值为 null，用于根据商品单位名称进行搜索
    },
    // 定义表单数据模型，用于存储表单中的数据，如新增或修改商品单位时的信息
    form: {},
    // 定义表单验证规则，这里规定单位名称不能为空，确保用户输入有效的商品单位名称
    rules: {
        name: [{ required: true, message: "单位名称不能为空", trigger: "blur" }]
    }
});

// 使用 toRefs 将响应式对象 data 中的属性转换为响应式引用，方便在模板中使用，避免响应式丢失问题
const { queryParams, form, rules } = toRefs(data);

/* 查询列表 */
function getList() {
    // 开始加载数据，将 loading 状态设置为 true，显示加载动效，提示用户数据正在加载中
    loading.value = true;
    // 调用 listProductUnit 接口函数，传入搜索参数，向服务器请求商品单位列表数据
    listProductUnit(queryParams.value).then((response) => {
        // 将接口返回的产品单位列表数据赋值给 productUnitList，更新表格显示的数据
        productUnitList.value = response.rows;
        // 将接口返回的总记录数赋值给 total，更新分页组件显示的总记录数
        total.value = response.total;
        // 数据加载完成，将 loading 状态设置为 false，隐藏加载动效，提示用户数据加载完成
        loading.value = false;
    });
}

/* 搜索按钮操作 */
function handleQuery() {
    // 点击搜索按钮时，调用 getList 函数重新获取列表数据，根据新的搜索条件更新表格数据
    getList();
}

/* 重置按钮操作 */
function resetQuery() {
    // 调用 proxy 上的 resetForm 方法重置表单，参数为表单引用名称 "queryRef"，将搜索表单的数据重置为初始值
    proxy.resetForm("queryRef");
    // 重置表单后，调用 getList 函数重新获取列表数据，显示未筛选的商品单位列表
    handleQuery();
}

/* 弹出表单重置 */
function reset() {
    // 重置表单数据，将 id 和 name 置为 null，清空表单中的数据，为新增或修改操作做准备
    form.value = {
        id: null,
        name: null
    };
    // 调用 proxy 上的 resetForm 方法重置表单，参数为表单的引用名称 "productUnitRef"，重置表单的验证状态等
    proxy.resetForm("productUnitRef");
}

/* 弹出表单取消按钮 */
function cancel() {
    // 关闭弹出层，将 open 状态设置为 false，隐藏新增或修改弹出层
    open.value = false;
    // 重置表单数据，清空表单中的数据，避免下次打开弹出层时显示上次的数据
    reset();
}

/* 新增按钮 */
function handleAdd() {
    // 重置表单数据，清空表单中的数据，确保新增操作时表单为初始状态
    reset();
    // 打开弹出层，将 open 状态设置为 true，显示新增商品单位的弹出层
    open.value = true;
    // 设置弹出层标题为添加商品单位，提示用户当前操作类型
    title.value = "添加商品单位";
}

/* 修改按钮操作 */
function handleUpdate(row) {
    // 重置表单数据，清空表单中的数据，为修改操作做准备
    reset();
    // 获取要修改的产品单位的 id，如果传入了 row 则取 row.id，否则取 ids.value，支持单选和多选修改
    const _id = row.id || ids.value;
    // 调用 getProductUnit 接口函数，根据 id 获取产品单位的详细信息，填充到表单中
    getProductUnit(_id).then((response) => {
        // 将获取到的详细信息赋值给表单数据，更新表单中的商品单位信息
        form.value = response.data;
        // 打开弹出层，将 open 状态设置为 true，显示修改商品单位的弹出层
        open.value = true;
        // 设置弹出层标题为修改商品单位，提示用户当前操作类型
        title.value = "修改商品单位";
    });
}

/* 弹出表单提交按钮 */
function submitForm() {
    // 对表单进行验证，验证通过后执行回调函数，确保用户输入的数据符合表单验证规则
    proxy.$refs["productUnitRef"].validate((valid) => {
        if (valid) {
            if (form.value.id != null) {
                // 若表单数据中存在 id，说明是修改操作，调用 updateProductUnit 接口函数更新数据
                updateProductUnit(form.value).then(() => {
                    // 显示修改成功的消息提示，使用 proxy 上的 $modal.msgSuccess 方法，提示用户修改操作成功
                    proxy.$modal.msgSuccess("修改成功");
                    // 关闭弹出层，将 open 状态设置为 false，隐藏修改商品单位的弹出层
                    open.value = false;
                    // 重新获取列表数据，调用 getList 函数，更新表格显示的商品单位列表
                    getList();
                });
            } else {
                // 若表单数据中不存在 id，说明是新增操作，调用 addProductUnit 接口函数添加数据
                addProductUnit(form.value).then(() => {
                    // 显示新增成功的消息提示，使用 proxy 上的 $modal.msgSuccess 方法，提示用户新增操作成功
                    proxy.$modal.msgSuccess("新增成功");
                    // 关闭弹出层，将 open 状态设置为 false，隐藏新增商品单位的弹出层
                    open.value = false;
                    // 重新获取列表数据，调用 getList 函数，更新表格显示的商品单位列表
                    getList();
                });
            }
        }
    });
}

// 多选框选中数据
function handleSelectionChange(selection) {
    // 将选中的产品单位的 id 存储到 ids 数组中，方便进行批量删除等操作
    ids.value = selection.map((item) => item.id);
    // 判断是否只选中了一条记录，更新 single 状态，控制修改按钮的禁用状态
    single.value = selection.length !== 1;
    // 更新 multiple 状态，控制删除按钮的禁用状态
    multiple.value = !selection.length;
}

// 删除按钮操作
function handleDelete(row) {
    const _id = row.id || ids.value;
    // 弹出确认对话框，询问用户是否确认删除商品单位，使用 proxy 上的 $modal.confirm 方法
    proxy.$modal.confirm('是否确认删除商品单位编号为"' + _id + '"的数据项？').then(function () {
        // 若用户确认删除，调用 deleteProductUnit 接口函数删除数据
        return deleteProductUnit(_id);
    }).then(() => {
        // 删除成功后，重新获取列表数据，调用 getList 函数，更新表格显示的商品单位列表
        getList();
        // 显示删除成功的消息提示，使用 proxy 上的 $modal.msgSuccess 方法，提示用户删除操作成功
        proxy.$modal.msgSuccess("删除成功");
    }).catch(() => {
        // 处理删除失败的情况，可根据需要添加具体的错误处理逻辑
    });
}

// 组件挂载后，首次调用 getList 函数获取列表数据，确保页面加载时显示商品单位列表
getList();

</script>

<!--
  <template> 标签部分用于编写组件的 HTML 结构，也就是组件的视图部分。
  在这个部分，我们使用了 Element UI 提供的各种组件来构建一个完整的页面，
  包括搜索表单、功能按钮栏、数据展示表格、分页条组件以及新增与修改弹出层。
  这些组件会根据 <script> 部分定义的数据进行动态渲染。
-->
<template>
    <!-- 整个页面的容器，使用 app-container 类名进行样式控制，可在 CSS 中对该类名进行样式设置 -->
    <div class="app-container">

        <!-- 搜索表单 -->
        <!-- el-form 是 Element UI 提供的表单组件，用于创建一个表单 -->
        <!-- v-show="showSearch" 根据 showSearch 的值决定是否显示表单，实现搜索框的显示与隐藏控制 -->
        <!-- ref="queryRef" 为表单组件注册一个引用名称，方便在 JavaScript 中操作表单，如重置表单等 -->
        <!-- :inline="true" 设置表单为行内布局，使表单项水平排列，提高页面空间利用率 -->
        <!-- :model="queryParams" 将表单数据与 queryParams 对象绑定，实现双向数据绑定，方便获取用户输入的搜索条件 -->
        <!-- label-width="68px" 设置表单标签的统一宽度，使表单布局更加整齐 -->
        <el-form v-show="showSearch" ref="queryRef" :inline="true" :model="queryParams" label-width="68px">
            <!-- el-form-item 是表单中的表单项组件，用于包裹具体的表单控件 -->
            <!-- label="单位名称" 为表单项设置标签文本，提示用户输入的内容 -->
            <!-- prop="name" 关联表单验证时的数据对象属性，与表单验证规则中的 name 对应 -->
            <el-form-item label="单位名称" prop="name">
                <!-- el-input 是输入框组件，用于用户输入文本信息 -->
                <!-- v-model="queryParams.name" 将输入框的值与 queryParams 对象的 name 属性绑定，实现双向数据绑定，方便获取用户输入的商品单位名称 -->
                <!-- clearable 显示清空图标，方便用户清空输入内容，提高用户体验 -->
                <!-- placeholder="请输入单位名称" 提供输入提示信息，引导用户输入正确的内容 -->
                <el-input v-model="queryParams.name" clearable placeholder="请输入单位名称"/>
            </el-form-item>
            <el-form-item>
                <!-- el-button 是按钮组件 -->
                <!-- icon="Search" 显示搜索图标，直观提示用户该按钮的功能 -->
                <!-- type="primary" 设置按钮为主要类型，通常有突出的样式，吸引用户注意 -->
                <!-- @click="handleQuery" 绑定点击事件，点击按钮时调用 handleQuery 函数，触发搜索操作 -->
                <el-button icon="Search" type="primary" @click="handleQuery">搜索</el-button>
                <!-- icon="Refresh" 显示刷新图标，直观提示用户该按钮的功能 -->
                <!-- @click="resetQuery" 绑定点击事件，点击按钮时调用 resetQuery 函数，触发重置操作 -->
                <el-button icon="Refresh" @click="resetQuery">重置</el-button>
            </el-form-item>
        </el-form>

        <!-- 功能按钮栏 -->
        <!-- el-row 是 Element UI 的栅格系统行组件，用于水平布局 -->
        <!-- :gutter="10" 设置列之间的间距为 10px，使按钮之间有适当的间隔，提高页面美观度 -->
        <!-- class="mb8" 添加一个类名，用于设置底部外边距，使按钮栏与下方表格有一定的间距 -->
        <el-row :gutter="10" class="mb8">
            <!-- el-col 是栅格系统列组件，用于划分列的宽度 -->
            <!-- :span="1.5" 设置列的宽度为 1.5 份（总共 24 份），根据页面布局需求设置按钮的宽度 -->
            <el-col :span="1.5">
                <!-- el-button 按钮组件 -->
                <!-- icon="Plus" 显示加号图标，直观提示用户该按钮的功能 -->
                <!-- plain 设置按钮为朴素样式，使按钮外观更加简洁 -->
                <!-- type="primary" 设置按钮为主要类型，通常有突出的样式，吸引用户注意 -->
                <!-- @click="handleAdd" 绑定点击事件，点击按钮时调用 handleAdd 函数，触发新增商品单位操作 -->
                <el-button
                    icon="Plus"
                    plain
                    type="primary"
                    @click="handleAdd"
                >新增
                </el-button>
            </el-col>
            <el-col :span="1.5">
                <!-- el-button 按钮组件 -->
                <!-- icon="Edit" 显示编辑图标，直观提示用户该按钮的功能 -->
                <!-- plain 设置按钮为朴素样式，使按钮外观更加简洁 -->
                <!-- type="success" 设置按钮为成功类型，通常有绿色样式，与修改操作的成功含义相呼应 -->
                <!-- :disabled="single" 根据 single 的值控制按钮的禁用状态，当只选中一条记录时可进行修改操作 -->
                <el-button
                    :disabled="single"
                    icon="Edit"
                    plain
                    type="success"
                    @click="handleUpdate"
                >修改
                </el-button>
            </el-col>
            <el-col :span="1.5">
                <!-- el-button 按钮组件 -->
                <!-- icon="Delete" 显示删除图标，直观提示用户该按钮的功能 -->
                <!-- plain 设置按钮为朴素样式，使按钮外观更加简洁 -->
                <!-- type="danger" 设置按钮为危险类型，通常有红色样式，与删除操作的危险性相呼应 -->
                <!-- :disabled="multiple" 根据 multiple 的值控制按钮的禁用状态，当有选中记录时可进行删除操作 -->
                <el-button
                    :disabled="multiple"
                    icon="Delete"
                    plain
                    type="danger"
                    @click="handleDelete"
                >删除
                </el-button>
            </el-col>
            <!-- 右侧工具栏组件 -->
            <!-- v-model:show-search="showSearch" 双向绑定 showSearch 变量，控制搜索框的显示与隐藏，方便用户切换搜索框的显示状态 -->
            <!-- @queryTable="getList" 绑定 queryTable 事件，触发时调用 getList 函数，可用于刷新表格数据 -->
            <right-toolbar v-model:show-search="showSearch" @queryTable="getList"></right-toolbar>
        </el-row>

        <!-- 数据展示表格 -->
        <!-- el-table 是 Element UI 的表格组件，用于展示数据 -->
        <!-- :data="productUnitList" 绑定表格的数据来源，表格将显示 productUnitList 中的数据，根据数据动态渲染表格内容 -->
        <!-- v-loading="loading" 根据 loading 的值显示加载动效，当数据加载时显示加载动效，提高用户体验 -->
        <!-- @selection-change="handleSelectionChange" 监听表格的选中状态变化事件，调用 handleSelectionChange 函数，处理表格行的选中操作 -->
        <el-table v-loading="loading" :data="productUnitList" @selection-change="handleSelectionChange">
            <!-- el-table-column 是表格列组件，用于定义表格的列 -->
            <!-- align="center" 设置列内容居中对齐，使表格内容布局更加整齐 -->
            <!-- type="selection" 设置该列为选择列，用于勾选表格行，方便用户进行批量操作 -->
            <!-- width="55" 设置列的宽度为 55px，根据页面布局需求设置列的宽度 -->
            <el-table-column align="center" type="selection" width="55"/>
            <!-- label="单位名称" 设置列的标题，提示用户该列显示的内容 -->
            <!-- prop="name" 关联表格数据中的 name 属性，显示对应的数据，根据数据动态渲染表格列内容 -->
            <!-- width="200" 设置列的宽度为 200px，根据页面布局需求设置列的宽度 -->
            <el-table-column label="单位名称" prop="name" width="200"/>
            <!-- label="创建时间" 设置列的标题，提示用户该列显示的内容 -->
            <!-- prop="createTime" 关联表格数据中的 createTime 属性，显示对应的数据，根据数据动态渲染表格列内容 -->
            <el-table-column label="创建时间" prop="createTime"/>
            <!-- align="center" 设置列内容居中对齐，使表格内容布局更加整齐 -->
            <!-- class-name="small-padding fixed-width" 添加类名，用于样式控制，可在 CSS 中对该类名进行样式设置 -->
            <!-- label="操作" 设置列的标题，提示用户该列的操作功能 -->
            <!-- width="200" 设置列的宽度为 200px，根据页面布局需求设置列的宽度 -->
            <el-table-column align="center" class-name="small-padding fixed-width" label="操作" width="200">
                <!-- template #default="scope" 定义表格列的内容模板 -->
                <!-- scope 包含当前行的数据信息，可通过 scope.row 访问当前行的数据 -->
                <template #default="scope">
                    <!-- el-button 按钮组件 -->
                    <!-- icon="Edit" 显示编辑图标，直观提示用户该按钮的功能 -->
                    <!-- link 设置按钮为链接样式，使按钮外观更加简洁 -->
                    <!-- type="primary" 设置按钮为主要类型，通常有突出的样式，吸引用户注意 -->
                    <!-- @click="handleUpdate(scope.row)" 绑定点击事件，点击按钮时调用 handleUpdate 函数，传入当前行的数据，触发修改操作 -->
                    <el-button icon="Edit" link type="primary" @click="handleUpdate(scope.row)">修改</el-button>
                    <!-- el-button 按钮组件 -->
                    <!-- icon="Delete" 显示删除图标，直观提示用户该按钮的功能 -->
                    <!-- link 设置按钮为链接样式，使按钮外观更加简洁 -->
                    <!-- type="primary" 设置按钮为主要类型，通常有突出的样式，吸引用户注意 -->
                    <!-- @click="handleDelete(scope.row)" 绑定点击事件，点击按钮时调用 handleDelete 函数，传入当前行的数据，触发删除操作 -->
                    <el-button icon="Delete" link type="primary" @click="handleDelete(scope.row)">删除</el-button>
                </template>
            </el-table-column>
        </el-table>

        <!-- 分页条组件 -->
        <!-- v-show="total > 0" 根据总记录数判断是否显示分页组件，当总记录数大于 0 时显示，避免在没有数据时显示分页组件 -->
        <!-- v-model:limit="queryParams.pageSize" 双向绑定每页显示数量，可通过分页组件修改每页显示的记录数 -->
        <!-- v-model:page="queryParams.pageNum" 双向绑定当前页码，可通过分页组件切换当前页码 -->
        <!-- :total="total" 绑定分页组件的总记录数，根据总记录数计算分页信息 -->
        <!-- @pagination="getList" 绑定分页事件，页码或每页数量改变时调用 getList 函数，更新表格数据 -->
        <pagination v-show="total > 0" v-model:limit="queryParams.pageSize" v-model:page="queryParams.pageNum"
                    :total="total" @pagination="getList"/>

        <!-- 添加或修改商品单位对话框 -->
        <!-- v-model="open" 双向绑定 open 变量，控制对话框的显示与隐藏，方便用户进行新增或修改操作 -->
        <!-- :title="title" 动态设置对话框的标题，根据操作类型显示不同的标题，提示用户当前操作类型 -->
        <!-- append-to-body 将对话框添加到 body 元素中，避免对话框受到父元素样式的影响 -->
        <!-- width="500px" 设置对话框的宽度为 500px，根据页面布局需求设置对话框的宽度 -->
        <el-dialog v-model="open" :title="title" append-to-body width="500px">
            <!-- el-form 是表单组件，用于创建表单 -->
            <!-- ref="productUnitRef" 为表单组件注册一个引用名称，方便在 JavaScript 中操作表单，如表单验证等 -->
            <!-- :model="form" 将表单数据与 form 对象绑定，实现双向数据绑定，方便获取用户输入的表单数据 -->
            <!-- :rules="rules" 绑定表单验证规则，确保用户输入的数据符合表单验证规则 -->
            <!-- label-width="80px" 设置表单标签的统一宽度，使表单布局更加整齐 -->
            <el-form ref="productUnitRef" :model="form" :rules="rules" label-width="80px">
                <!-- el-form-item 是表单项组件，用于包裹具体的表单控件 -->
                <!-- label="单位名称" 为表单项设置标签文本，提示用户输入的内容 -->
                <!-- prop="name" 关联表单验证时的数据对象属性，与表单验证规则中的 name 对应 -->
                <el-form-item label="单位名称" prop="name">
                    <!-- el-input 是输入框组件，用于用户输入文本信息 -->
                    <!-- v-model="form.name" 将输入框的值与 form 对象的 name 属性绑定，实现双向数据绑定，方便获取用户输入的商品单位名称 -->
                    <!-- placeholder="请输入单位名称" 提供输入提示信息，引导用户输入正确的内容 -->
                    <el-input v-model="form.name" placeholder="请输入单位名称"/>
                </el-form-item>
            </el-form>
            <!-- template #footer 定义对话框底部的内容模板 -->
            <template #footer>
                <div class="dialog-footer">
                    <!-- el-button 按钮组件 -->
                    <!-- type="primary" 设置按钮为主要类型，通常有突出的样式，吸引用户注意 -->
                    <!-- @click="submitForm" 绑定点击事件，点击按钮时调用 submitForm 函数，触发表单提交操作 -->
                    <el-button type="primary" @click="submitForm">确 定</el-button>
                    <!-- el-button 按钮组件 -->
                    <!-- @click="cancel" 绑定点击事件，点击按钮时调用 cancel 函数，触发取消操作 -->
                    <el-button @click="cancel">取 消</el-button>
                </div>
            </template>
        </el-dialog>
    </div>
</template>

<!--
  <style> 标签部分用于编写组件的样式代码。
  lang="scss" 表示使用 SCSS 预处理器来编写样式，SCSS 是 CSS 的扩展，提供了更多的功能，如变量、嵌套等。
  scoped 属性表示这些样式只作用于当前组件，不会影响到其他组件。
  在这个部分，我们可以对页面中的元素进行样式定制，使其符合设计要求。
-->
<style lang="scss" scoped>
    /* 这里可以编写组件的样式代码，scoped 表示样式只作用于当前组件 */
</style>